Type.registerNamespace("BM");

// RestrictionType enumeration
BM.RestrictionType = function() { };
BM.RestrictionType.prototype =
{
    Length: 0,
    MaxLength: 1,
    MinLength: 2,
    MaxExclusive: 3,
    MinExclusive: 4,
    MaxInclusive: 5,
    MinInclusive: 6,
    Pattern: 7,
    FractionDigits: 8,
    TotalDigits: 9
}
BM.RestrictionType.registerEnum("BM.RestrictionType", false);

// Restriction object

BM.Restriction = function(leafItem, data) {
    BM.Restriction.initializeBase(this, [leafItem, data]);
}

BM.Restriction.prototype = {

    getRestrictionType: function() {
        ///	<summary>
        ///	returns constraint type (maximal length, minimal length, etc.)
        ///	</summary>
        ///	<returns type="String" />
        return this.getProperty('type');
    },

    setRestrictionType: function (value) {
        ///	<summary>
        ///	sets the constraint type (maximal length, minimal length, etc.)
        ///	</summary>
        ///	<param name="value" type="BM.RestrictionType" mayBeBull="false">
        ///	a restriction type
        ///	</param>
        return this.setProperty('type', value);
    },

    getRestriction: function() {
        ///	<summary>
        ///	returns the value to which the constraint is restricted
        ///	</summary>
        ///	<returns type="String" /> 
        return this.getProperty('value');
    },

    setRestriction: function (value) {
        ///	<summary>
        ///	sets the value to which the constraint is restricted
        ///	</summary>
        ///	<param name="value" type="String" mayBeBull="false">
        ///	a restriction value
        ///	</param>
        this.setProperty('value', value);
    },

    getDataTypeValue: function() {
        return this.getItem().getDataTypeValue();
    },

    getRestrictionAsNumber: function() {
        return parseFloat(this.getRestriction());
    },

    isMet: function() {
        switch (this.getRestrictionType()) {
            case BM.RestrictionType.Length:
                return BM.Restriction.isExactLength(this.getValue(), this.getRestrictionAsNumber());
            case BM.RestrictionType.MaxLength:
                return !BM.Restriction.isLongerThan(this.getValue(), this.getRestrictionAsNumber());
            case BM.RestrictionType.MinLength:
                return !BM.Restriction.isShorterThan(this.getValue(), this.getRestrictionAsNumber());
            case BM.RestrictionType.MinInclusive:
                return !BM.Restriction.isSmallerThan(this.getDataTypeValue(), this.getRestrictionAsNumber());
            case BM.RestrictionType.MaxInclusive:
                return !BM.Restriction.isLargerThan(this.getDataTypeValue(), this.getRestrictionAsNumber());
            case BM.RestrictionType.MinExclusive:
                return BM.Restriction.isLargerThan(this.getDataTypeValue(), this.getRestrictionAsNumber());
            case BM.RestrictionType.MaxExclusive:
                return BM.Restriction.isSmallerThan(this.getDataTypeValue(), this.getRestrictionAsNumber());
            case BM.RestrictionType.Pattern:
                return BM.Restriction.matchRegExp(this.getValue(), this.getRestriction());
            case BM.RestrictionType.TotalDigits:
                return BM.Restriction.hasTotalDigits(this.getDataTypeValue(), this.getRestrictionAsNumber());
            case BM.RestrictionType.FractionDigits:
                return BM.Restriction.hasFractionDigits(this.getDataTypeValue(), this.getRestrictionAsNumber());
        }
        return true;
    },

    getDefaultErrorText: function() {
        return BM.RestrictionErrors[BM.RestrictionType.toString(this.getRestrictionType())] + " " + this.getRestriction();
    },

    addCurrent: function(parent, value) {
        BM.NodeBuilder.createSpan(parent, 'Current', '(' + value + ')');
    },

    appendDescription: function(node) {
        if (this.getInfoText() != null) {
            BM.Restriction.callBaseMethod(this, 'appendDescription', [node]);
            return;
        }

        this.appendInferredDescription(node);
    },

    appendInferredDescription: function(node) {
        var ct = BM.NodeBuilder.createDiv(node, "Constraint");
        BM.NodeBuilder.createSpan(ct, 'Type', BM.RestrictionTypes[BM.RestrictionType.toString(this.getRestrictionType())] + ':');
        BM.NodeBuilder.createSpan(ct, 'Value', this.getRestriction());
        switch (this.getRestrictionType()) {
            case BM.RestrictionType.TotalDigits:
                this.addCurrent(ct, BM.Restriction.getTotalDigits(this.getDataTypeValue()));
                break;
            case BM.RestrictionType.FractionDigits:
                this.addCurrent(ct, BM.Restriction.getFractionDigits(this.getDataTypeValue()));
                break;
            case BM.RestrictionType.Length:
            case BM.RestrictionType.MaxLength:
            case BM.RestrictionType.MinLength:
                this.addCurrent(ct, this.getValue().length);
                break;
            case BM.RestrictionType.MaxInclusive:
            case BM.RestrictionType.MinInclusive:
            case BM.RestrictionType.MaxExclusive:
            case BM.RestrictionType.MinExclusive:
                this.addCurrent(ct, this.getValue());
                break;
        }
    }
}

BM.Restriction.registerClass("BM.Restriction", BM.Constraint);

/* length, size, regex tests */
BM.Restriction.isLargerThan = function(fieldValue, number) {
    return (fieldValue > number);
}

BM.Restriction.isSmallerThan = function(fieldValue, number) {
    return (fieldValue < number);
}

BM.Restriction.isShorterThan = function(fieldValue, number) {
    return (fieldValue.length < number);
}

BM.Restriction.isLongerThan = function(fieldValue, number) {
    return (fieldValue.length > number);
}

BM.Restriction.isExactLength = function(fieldValue, number) {
    return (fieldValue.length == number);
}

BM.Restriction.matchRegExp = function(fieldValue, exp) {
    exp = new RegExp('^' + exp + '$');
    try {
        return fieldValue.match(exp);
    } catch (err) {
        alert('Invalid regular expression:' + exp);
        return true;
    }
}

BM.Restriction.getTotalDigits = function(fieldValue) {
    var fieldValueText = new String(fieldValue);
    var digits = fieldValueText.length;
    if (fieldValueText.lastIndexOf('.') != -1) {
        digits--;
    }
    return parseInt(digits);
}

BM.Restriction.getFractionDigits = function(fieldValue) {
    var fieldValueText = new String(fieldValue);
    var dot = fieldValueText.lastIndexOf('.');
    var digits = 0;
    if (dot != -1) {
        digits = fieldValueText.length - dot - 1;
    }
    return parseInt(digits);
}

BM.Restriction.hasTotalDigits = function(fieldValue, value) {
    return BM.Restriction.getTotalDigits(fieldValue) <= value;
}

BM.Restriction.hasFractionDigits = function(fieldValue, value) {
    return BM.Restriction.getFractionDigits(fieldValue) <= value;
}


